package lt.liepasoft.locr.realization;

import java.util.ArrayList;
import java.util.List;
import lt.liepasoft.locr.ImageManager;
import lt.liepasoft.locr.Scanner;
import lt.liepasoft.locr.data.*;

public class FloodFillScanner 
    extends Scanner {

    @Override
    public List<Symbol> scan(OcrImage ocrImage, Bounds bounds) {
        List <Symbol> symbols = new ArrayList<>();        
        SymbolImage image = ImageManager.createSymbolImage(ocrImage, whiteThreshold, invert);
        
        Symbol symbol;
        for (int y=0; y<image.height; y++){
            for (int x=0; x<image.width; x++){            
                if (image.getPixel(x, y))
                    if ((symbol=floodFill(image, x, y)) != null)
                        symbols.add(symbol);
            }
        }
        return symbols;
    }     
    
  // implements the flood fill algorithm
    private Symbol floodFill(SymbolImage image, int x, int y){
	    List<Point> 
	            examList = new ArrayList<>(),
	            symbolPoints = new ArrayList<>();
	 
	    Point 
	        tl = new Point(Integer.MAX_VALUE, Integer.MAX_VALUE), //TOP-LEFT
	        br = new Point(Integer.MIN_VALUE, Integer.MIN_VALUE); //BOTTOM-RIGHT
	 
	    examList.add(new Point(x,y));
	 
	    while (examList.size()>0){
	      Point p = examList.remove(0);  // get and remove the first point in the list
	      //System.out.println(p.x+" "+p.y);
	      if (image.getPixel(p.x, p.y)) {
	        x = p.x;  y = p.y;
	        image.setPixel(false, x, y);        
	        symbolPoints.add(p);
	        
	        if (x<tl.x)
	            tl.x=x;
	        if(y<tl.y)
	            tl.y=y;
	        
	        if (x>br.x)
	            br.x=x;
	        if(y>br.y)
	            br.y=y;
	        //most top, down, left and right to find
	        if (x > 0)
	            examList.add(new Point(x-1,y));        // check west neighbor
	        if (x < image.width-1)
	            examList.add(new Point(x+1,y));        // check east neighbor
	        if (y > 0)
	            examList.add(new Point(x,y-1));        // check north neighbor
	        if (y < image.height-1)
	            examList.add(new Point(x,y+1));        // check south neighbor
	      }
    }	
 
    int symbolOriginalWidth = br.x-tl.x+1;    
    int symbolOriginalHeight = br.y-tl.y+1;    
//    
//    if (symbolOriginalWidth <= 16 || symbolOriginalHeight <= 16)
//        return null;
    
    SymbolImage symbolImg = new SymbolImage(symbolOriginalWidth, symbolOriginalHeight);
    
    for (Point p: symbolPoints){
        symbolImg.setPixel(true, p.x-tl.x, p.y-tl.y);
    }
    
    symbolImg = ImageManager.scale(symbolImg, 16, 16);
    //make a symbol from it
    
    //System.out.println("-> "+symbolImg.width+" "+symbolImg.height+" "+symbolImg.getBlackPixels());
    //System.out.println("symbol size: "+symbolPoints.size());
    
    //check for black pixels count in image
    if (symbolImg.getBlackPixels() < 50 || 200 < symbolImg.getBlackPixels())
        return null;
    
    Symbol symbol = new Symbol(new Bounds(tl.x, tl.y, br.x, br.y), symbolImg);
    
    return symbol;
  }
}
